package s10338;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Radosław Wichrowski s10338
 */
public class Network {

    private int spodziewaneWyjscie;
    private String numerIndeksu;
    private WarstwaPierwsza warstwa1;
    private WarstwaDruga warstwa2;
    private WarstwaTrzecia warstwa3;
    private int ilePrawidlowych = 0;

    public Network() {
    }

    public double getSpodziewaneWyjscie() {
        return spodziewaneWyjscie;
    }

    public int getSpodziewaneWyjscieInt() {
        return spodziewaneWyjscie;
    }

    public void setSpodziewaneWyjscie(int spodziewaneWyjscie) {
        this.spodziewaneWyjscie = spodziewaneWyjscie;
    }

    public void startObliczen(String wierszTestu) throws Exception {
        if (wierszTestu == null) {
            throw new Exception("Brak danych wejściowych");
        }
// warstwa pierwsza
        List<Double> listaWejsc;
        List<Neuron> listaNeuronow;
        int liczbaIn = 0;
        String[] split = wierszTestu.split(";");

        listaNeuronow = new ArrayList();
        int i = 0;
        numerIndeksu = "";
        for (String wejscia : split) {
            liczbaIn = 0;
            listaWejsc = new ArrayList<>();
            String[] split1 = wejscia.split("");
            for (String liczba : split1) {
                if (liczba.equals("")) {
                    continue;
                }
                Double wejscie = new Double(liczba);
                liczbaIn += wejscie;
                listaWejsc.add(wejscie);
            }
            numerIndeksu = numerIndeksu + (new Integer(liczbaIn)).toString();
            if (warstwa1 == null) {
                listaNeuronow.add(new Neuron(listaWejsc, getRandomDouble(listaWejsc.size()), true));
            } else {
                listaNeuronow.add(new Neuron(listaWejsc, warstwa1.getListaNeronow().get(i).getListaWag()));
            }
        }
        spodziewaneWyjscie = numerIndeksu.equals("10338") ? 1 : 0;
        if (spodziewaneWyjscie == 1) {
            ilePrawidlowych++;
        }
        if (warstwa1 == null) {
            warstwa1 = new WarstwaPierwsza();
        }
        warstwa1.setListaNeronow(listaNeuronow);

// warstwa druga
        List<Double> wejsciaPojNeuronu;
        listaNeuronow = new ArrayList();
        wejsciaPojNeuronu = new ArrayList<>();
        wejsciaPojNeuronu.add(warstwa1.getNeuronP1().getWyjscie());
        wejsciaPojNeuronu.add(warstwa1.getNeuronP2().getWyjscie());
        wejsciaPojNeuronu.add(warstwa1.getNeuronP3().getWyjscie());
        if (warstwa2 == null) {
            listaNeuronow.add(new Neuron(wejsciaPojNeuronu, getRandomDouble(wejsciaPojNeuronu.size()), true));
        } else {
            listaNeuronow.add(new Neuron(wejsciaPojNeuronu, warstwa2.getNeuronP1().getListaWag()));
        }

        wejsciaPojNeuronu = new ArrayList<>();
        wejsciaPojNeuronu.add(warstwa1.getNeuronP2().getWyjscie());
        wejsciaPojNeuronu.add(warstwa1.getNeuronP3().getWyjscie());
        wejsciaPojNeuronu.add(warstwa1.getNeuronP4().getWyjscie());
        if (warstwa2 == null) {
            listaNeuronow.add(new Neuron(wejsciaPojNeuronu, getRandomDouble(wejsciaPojNeuronu.size()), true));
        } else {
            listaNeuronow.add(new Neuron(wejsciaPojNeuronu, warstwa2.getNeuronP2().getListaWag()));
        }

        wejsciaPojNeuronu = new ArrayList<>();
        wejsciaPojNeuronu.add(warstwa1.getNeuronP3().getWyjscie());
        wejsciaPojNeuronu.add(warstwa1.getNeuronP4().getWyjscie());
        wejsciaPojNeuronu.add(warstwa1.getNeuronP5().getWyjscie());
        if (warstwa2 == null) {
            listaNeuronow.add(new Neuron(wejsciaPojNeuronu, getRandomDouble(wejsciaPojNeuronu.size()), true));
        } else {
            listaNeuronow.add(new Neuron(wejsciaPojNeuronu, warstwa2.getNeuronP3().getListaWag()));
        }

        warstwa2 = new WarstwaDruga(listaNeuronow);
// warstwa trzecia
        wejsciaPojNeuronu = new ArrayList<>();
        wejsciaPojNeuronu.add(warstwa2.getNeuronP1().getWyjscie());
        wejsciaPojNeuronu.add(warstwa2.getNeuronP2().getWyjscie());
        wejsciaPojNeuronu.add(warstwa2.getNeuronP2().getWyjscie());
        if (warstwa3 == null) {
            warstwa3 = new WarstwaTrzecia(new Neuron(wejsciaPojNeuronu, getRandomDouble(wejsciaPojNeuronu.size()), true));
        } else {
            warstwa3 = new WarstwaTrzecia(new Neuron(wejsciaPojNeuronu, warstwa3.getNeuronP1().getListaWag()));
        }
    }

    public WarstwaPierwsza getWarstwa1() {
        return warstwa1;
    }

    public WarstwaDruga getWarstwa2() {
        return warstwa2;
    }

    public WarstwaTrzecia getWarstwa3() {
        return warstwa3;
    }

    public String getNumerIndeksu() {
        return numerIndeksu;
    }

    public void wyliczBledy() {
        warstwa3.getNeuronP1().setBlad(spodziewaneWyjscie - warstwa3.getNeuronP1().getWyjscie());

//        warstwa3.getNeuronP1().setBlad(Math.pow(spodziewaneWyjscie - warstwa3.getNeuronP1().getWyjscie(), 2) / 2);
        warstwa2.getNeuronP1().setBlad(warstwa3.getNeuronP1().getBlad() * warstwa3.getNeuronP1().getListaWag().get(0) * (1 - warstwa2.getNeuronP1().getWyjscie()) * warstwa2.getNeuronP1().getWyjscie());
        warstwa2.getNeuronP2().setBlad(warstwa3.getNeuronP1().getBlad() * warstwa3.getNeuronP1().getListaWag().get(1) * (1 - warstwa2.getNeuronP2().getWyjscie()) * warstwa2.getNeuronP2().getWyjscie());
        warstwa2.getNeuronP3().setBlad(warstwa3.getNeuronP1().getBlad() * warstwa3.getNeuronP1().getListaWag().get(2) * (1 - warstwa2.getNeuronP3().getWyjscie()) * warstwa2.getNeuronP3().getWyjscie());

        warstwa1.getNeuronP1().setBlad(warstwa2.getNeuronP1().getBlad() * warstwa2.getNeuronP1().getListaWag().get(0) * (1 - warstwa1.getNeuronP1().getWyjscie()) * warstwa1.getNeuronP1().getWyjscie());
        warstwa1.getNeuronP2().setBlad(((warstwa2.getNeuronP1().getBlad() * warstwa2.getNeuronP1().getListaWag().get(1))
                + (warstwa2.getNeuronP2().getBlad() * warstwa2.getNeuronP2().getListaWag().get(0)))
                * (1 - warstwa1.getNeuronP2().getWyjscie()) * warstwa1.getNeuronP2().getWyjscie());
        warstwa1.getNeuronP3().setBlad(((warstwa2.getNeuronP1().getBlad() * warstwa2.getNeuronP1().getListaWag().get(2))
                + (warstwa2.getNeuronP2().getBlad() * warstwa2.getNeuronP2().getListaWag().get(1))
                + (warstwa2.getNeuronP3().getBlad() * warstwa2.getNeuronP3().getListaWag().get(0)))
                * (1 - warstwa1.getNeuronP3().getWyjscie()) * warstwa1.getNeuronP3().getWyjscie());
        warstwa1.getNeuronP4().setBlad(((warstwa2.getNeuronP2().getBlad() * warstwa2.getNeuronP2().getListaWag().get(2))
                + (warstwa2.getNeuronP3().getBlad() * warstwa2.getNeuronP3().getListaWag().get(1)))
                * (1 - warstwa1.getNeuronP4().getWyjscie()) * warstwa1.getNeuronP4().getWyjscie());
        warstwa1.getNeuronP5().setBlad(warstwa2.getNeuronP3().getBlad() * warstwa2.getNeuronP3().getListaWag().get(2) * (1 - warstwa1.getNeuronP5().getWyjscie()) * warstwa1.getNeuronP5().getWyjscie());

    }

    public void korektaWag() {
        warstwa3.getNeuronP1().korektaWag();

        warstwa2.getNeuronP1().korektaWag();
        warstwa2.getNeuronP2().korektaWag();
        warstwa2.getNeuronP3().korektaWag();

        warstwa1.getNeuronP1().korektaWag();
        warstwa1.getNeuronP2().korektaWag();
        warstwa1.getNeuronP3().korektaWag();
        warstwa1.getNeuronP4().korektaWag();
        warstwa1.getNeuronP5().korektaWag();

    }

    public void wyswietlWagi() {

//        System.out.println("wagi - warstwa 3 neuron 1 ");
        warstwa3.getNeuronP1().wyswietlWagi();

//        System.out.println("warstwa 2 neuron 1 ");
//        warstwa2.getNeuronP1().wyswietlWagi();
//        System.out.println("warstwa 2 neuron 2 ");
//        warstwa2.getNeuronP2().wyswietlWagi();
//        System.out.println("warstwa 2 neuron 3 ");
//        warstwa2.getNeuronP3().wyswietlWagi();
    }

    private List<Double> getRandomDouble(int size) {
//        System.out.println("getRandomDouble(" + size + ")");
        List wagi = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            wagi.add(Math.random() * 2 - 1);
//            System.out.println(Math.random() * 2 - 1);
        }
        return wagi;
    }

    public int getIlePrawidlowych() {
        return ilePrawidlowych;
    }

}
